package com.seed.core.table.impl;

import com.google.common.base.CaseFormat;
import com.seed.core.table.DataBaseTableServiceI;
import com.seed.core.table.entity.DataBaseTable;
import com.seed.core.table.entity.DataBaseTableDescribe;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author gchiaway
 * 日期: 2020-02-12
 * 时间: 18:01
 */
@Service("dataBaseTableService")
@Transactional(rollbackFor = Exception.class)
public class DataBaseTableServiceImpl implements DataBaseTableServiceI {

    /**
     * 根据数据库前缀,构造符合条件的表对象名称实体
     *
     * @param dataBaseTableDescribe 数据表名称前缀
     * @param tableNames            表名
     * @return 查出的表
     */
    @Override
    public List<DataBaseTable> listEntityNamesByTableNamesPrefix(DataBaseTableDescribe dataBaseTableDescribe, String... tableNames) {
        List<DataBaseTable> dataBaseTableList = new ArrayList<>();
        for (String tableName : tableNames) {
            //eg: 全表名为 seed_t_test_table
            DataBaseTable dataBaseTable = new DataBaseTable();
            if (tableName.startsWith(dataBaseTableDescribe.getProjectName() + dataBaseTableDescribe.getTablePrefix())) {
                //表名 eg: seed_t_test_table
                dataBaseTable.setTableName(tableName);
            } else {
                dataBaseTable.setTableName(dataBaseTableDescribe.getProjectName() + dataBaseTableDescribe.getTablePrefix() + tableName);
            }
            //项目名称 eg: seed_
            dataBaseTable.setProjectName(dataBaseTableDescribe.getProjectName());
            //表前缀 eg: t_
            dataBaseTable.setTablePrefix(dataBaseTableDescribe.getTablePrefix());

            //带前缀的小写名称 eg: seedttesttable
            dataBaseTable.setTableNameWithOutUnderline(dataBaseTable.getTableName().replaceAll("_", ""));

            //表的全前缀是由 项目名称+表前缀 组合而成 eg: seed_t_
            String tableNamesPrefix = dataBaseTableDescribe.getProjectName() + dataBaseTableDescribe.getTablePrefix();
            //实体名称 eg: test_table
            String entityName = dataBaseTable.getTableName().replaceAll(tableNamesPrefix, "");
            dataBaseTable.setEntityName(entityName);
            //实体名称没有下划线 eg: testtable
            dataBaseTable.setEntityNameWithOutUnderline(entityName.replaceAll("_", ""));

            //实体驼峰名称 eg: TestTable
            String entityNameHump = this.tableNameConvertUpperCamel(entityName);
            dataBaseTable.setEntityNameHump(entityNameHump);
            //实体驼峰名称首字母小写 eg: testTable
            String entityNameHumpFirstLow = this.tableNameConvertLowerCamel(entityName);
            dataBaseTable.setEntityNameHumpFirstLow(entityNameHumpFirstLow);

            //包名 eg:seed.t.testtable
            String entityPackage = dataBaseTable.getProjectName().replace("_", "") + "." + dataBaseTable.getTablePrefix().replace("_", "") + "." + dataBaseTable.getEntityNameWithOutUnderline();
            dataBaseTable.setEntityPackage(entityPackage);

            dataBaseTableList.add(dataBaseTable);
        }
        return dataBaseTableList;
    }

    /**
     * 构造符表对象名称实体
     *
     * @param tableNames 表名
     * @return 查出的表
     */
    @Override
    public List<DataBaseTable> listEntityNamesByTableNamesPrefix(String... tableNames) {
        if (StringUtils.isEmpty(tableNames)) {
            return null;
        }
        if (tableNames.length <= 0) {
            return null;
        }
        List<DataBaseTable> dataBaseTableList = new ArrayList<>();
        for (String tableName : tableNames) {
            String projectName = tableName.split("_")[0];
            String tablePrefix = tableName.split("_")[1].split("_")[0];
            DataBaseTableDescribe dataBaseTableDescribe = new DataBaseTableDescribe(projectName, tablePrefix);
            dataBaseTableList.addAll(listEntityNamesByTableNamesPrefix(dataBaseTableDescribe, tableName));
        }
        return dataBaseTableList;
    }

    /**
     * 格式化数据库表
     *
     * @param dataBaseTableDescribe 表前缀
     * @param dataBaseTableList     格式化前的表
     * @return 格式化完成后的表
     */
    private List<DataBaseTable> formatDataBaseTables(DataBaseTableDescribe dataBaseTableDescribe, List<DataBaseTable> dataBaseTableList) {
        for (DataBaseTable dataBaseTable : dataBaseTableList) {
            //eg: 全表名为 seed_t_test_table

            //项目名称 eg: seed_
            dataBaseTable.setProjectName(dataBaseTableDescribe.getProjectName());
            //表前缀 eg: t_
            dataBaseTable.setTablePrefix(dataBaseTableDescribe.getTablePrefix());

            //带前缀的小写名称 eg: seedttesttable
            dataBaseTable.setTableNameWithOutUnderline(dataBaseTable.getTableName().replaceAll("_", ""));

            //表的全前缀是由 项目名称+表前缀 组合而成 eg: seed_t_
            String tableNamesPrefix = dataBaseTableDescribe.getProjectName() + dataBaseTableDescribe.getTablePrefix();
            //实体名称 eg: test_table
            String entityName = dataBaseTable.getTableName().replaceAll(tableNamesPrefix, "");
            dataBaseTable.setEntityName(entityName);
            //实体名称没有下划线 eg: testtable
            dataBaseTable.setEntityNameWithOutUnderline(entityName.replaceAll("_", ""));

            //实体驼峰名称 eg: TestTable
            String entityNameHump = this.tableNameConvertUpperCamel(entityName);
            dataBaseTable.setEntityNameHump(entityNameHump);
            //实体驼峰名称首字母小写 eg: testTable
            String entityNameHumpFirstLow = this.tableNameConvertLowerCamel(entityName);
            dataBaseTable.setEntityNameHumpFirstLow(entityNameHumpFirstLow);
        }
        return dataBaseTableList;
    }

    /**
     * 驼峰名称
     *
     * @param tableName training_course
     * @return TrainingCourse
     */
    private String tableNameConvertUpperCamel(String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase());
    }

    /**
     * 驼峰名称
     *
     * @param tableName training_course
     * @return trainingCourse
     */
    private String tableNameConvertLowerCamel(String tableName) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase());
    }


}
